{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true,
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "### 列表生成式\n",
    "列表生成式即List Comprehensions，是Python内置的非常简单却强大的可以用来创建list的生成式。\n",
    "\n",
    "举个例子，要生成list `[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]`可以用`list(range(1, 11))`：\n",
    "\n",
    "```\n",
    ">>> list(range(1, 11))\n",
    "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n",
    "```\n",
    "\n",
    "但如果要生成`[1x1, 2x2, 3x3, ..., 10x10]`怎么做？方法一是循环：\n",
    "\n",
    "```\n",
    ">>> L = []\n",
    ">>> for x in range(1, 11):\n",
    "...    L.append(x * x)\n",
    "...\n",
    ">>> L\n",
    "[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]\n",
    "```\n",
    "\n",
    "但是循环太繁琐，而列表生成式则可以用一行语句代替循环生成上面的list：\n",
    "\n",
    "```\n",
    ">>> [x * x for x in range(1, 11)]\n",
    "[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]\n",
    "```\n",
    "\n",
    "写列表生成式时，把要生成的元素`x * x`放到前面，后面跟`for`循环，就可以把list创建出来，十分有用，多写几次，很快就可以熟悉这种语法。\n",
    "\n",
    "for循环后面还可以加上if判断，这样我们就可以筛选出仅偶数的平方：\n",
    "\n",
    "```\n",
    ">>> [x * x for x in range(1, 11) if x % 2 == 0]\n",
    "[4, 16, 36, 64, 100]\n",
    "```\n",
    "\n",
    "还可以使用两层循环，可以生成全排列：\n",
    "\n",
    "```\n",
    ">>> [m + n for m in 'ABC' for n in 'XYZ']\n",
    "['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']\n",
    "```\n",
    "\n",
    "三层和三层以上的循环就很少用到了。\n",
    "\n",
    "运用列表生成式，可以写出非常简洁的代码。例如，列出当前目录下的所有文件和目录名，可以通过一行代码实现：\n",
    "\n",
    "```\n",
    ">>> import os # 导入os模块，模块的概念后面讲到\n",
    ">>> [d for d in os.listdir('.')] # os.listdir可以列出文件和目录\n",
    "['.emacs.d', '.ssh', '.Trash', 'Adlm', 'Applications', 'Desktop', 'Documents', 'Downloads', 'Library', 'Movies', 'Music', 'Pictures', 'Public', 'VirtualBox VMs', 'Workspace', 'XCode']\n",
    "```\n",
    "\n",
    "`for`循环其实可以同时使用两个甚至多个变量，比如`dict`的`items()`可以同时迭代key和value：\n",
    "\n",
    "```\n",
    ">>> d = {'x': 'A', 'y': 'B', 'z': 'C' }\n",
    ">>> for k, v in d.items():\n",
    "...     print(k, '=', v)\n",
    "...\n",
    "y = B\n",
    "x = A\n",
    "z = C\n",
    "```\n",
    "\n",
    "因此，列表生成式也可以使用两个变量来生成list：\n",
    "\n",
    "```\n",
    ">>> d = {'x': 'A', 'y': 'B', 'z': 'C' }\n",
    ">>> [k + '=' + v for k, v in d.items()]\n",
    "['y=B', 'x=A', 'z=C']\n",
    "```\n",
    "\n",
    "最后把一个list中所有的字符串变成小写：\n",
    "\n",
    "```\n",
    ">>> L = ['Hello', 'World', 'IBM', 'Apple']\n",
    ">>> [s.lower() for s in L]\n",
    "['hello', 'world', 'ibm', 'apple']\n",
    "```\n",
    "\n",
    "### if ... else\n",
    "\n",
    "使用列表生成式的时候，有些童鞋经常搞不清楚`if...else`的用法。\n",
    "\n",
    "例如，以下代码正常输出偶数：\n",
    "\n",
    "```\n",
    ">>> [x for x in range(1, 11) if x % 2 == 0]\n",
    "[2, 4, 6, 8, 10]\n",
    "```\n",
    "\n",
    "但是，我们不能在最后的`if`加上`else`：\n",
    "\n",
    "```\n",
    ">>> [x for x in range(1, 11) if x % 2 == 0 else 0]\n",
    "  File \"<stdin>\", line 1\n",
    "    [x for x in range(1, 11) if x % 2 == 0 else 0]\n",
    "                                              ^\n",
    "SyntaxError: invalid syntax\n",
    "```\n",
    "\n",
    "这是因为跟在`for`后面的`if`是一个筛选条件，不能带`else`，否则如何筛选？\n",
    "\n",
    "另一些童鞋发现把`if`写在`for`前面必须加`else`，否则报错：\n",
    "\n",
    "```\n",
    ">>> [x if x % 2 == 0 for x in range(1, 11)]\n",
    "  File \"<stdin>\", line 1\n",
    "    [x if x % 2 == 0 for x in range(1, 11)]\n",
    "                       ^\n",
    "SyntaxError: invalid syntax\n",
    "```\n",
    "\n",
    "这是因为`for`前面的部分是一个表达式，它必须根据`x`计算出一个结果。因此，考察表达式：`x if x % 2 == 0`，它无法根据`x`计算出结果，因为缺少`else`，必须加上`else`：\n",
    "\n",
    "```\n",
    ">>> [x if x % 2 == 0 else -x for x in range(1, 11)]\n",
    "[-1, 2, -3, 4, -5, 6, -7, 8, -9, 10]\n",
    "```\n",
    "\n",
    "上述`for`前面的表达式`x if x % 2 == 0 else -x`才能根据`x`计算出确定的结果。\n",
    "\n",
    "可见，在一个列表生成式中，`for`前面的`if ... else`是表达式，而`for`后面的`if`是过滤条件，不能带`else`。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "outputs": [],
   "source": [
    "# 使用列表生成式\n",
    "L1 = ['Hello', 'World', 18, 'Apple', None]"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "outputs": [
    {
     "data": {
      "text/plain": "['hello', 'world', 'apple']"
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "L2 = [s.lower() for s in L1 if isinstance(s, str)]\n",
    "L2"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [],
   "metadata": {
    "collapsed": false
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}